package com.ruoyi.video.server.onvif.lib;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
import java.util.Timer;
import java.util.TimerTask;
import java.util.stream.Collectors;

/**
 * 通过广播消息的方式发现ONVIF设备
 */
public class BroadcastDiscovery {
    public static String DISCOVERY_PROBE_MESSAGE = "<soap:Envelope xmlns:soap=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:wsa=\"http://schemas.xmlsoap.org/ws/2004/08/addressing\" xmlns:tns=\"http://schemas.xmlsoap.org/ws/2005/04/discovery\"><soap:Header><wsa:Action>http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe</wsa:Action><wsa:MessageID>urn:uuid:c032cfdd-c3ca-49dc-820e-ee6696ad63e2</wsa:MessageID><wsa:To>urn:schemas-xmlsoap-org:ws:2005:04:discovery</wsa:To></soap:Header><soap:Body><tns:Probe/></soap:Body></soap:Envelope>";
    public static int DISCOVERY_PORT = 3702;
    public static String DISCOVERY_ADDRESS_IPV4 = "239.255.255.250";

    public static Logger logger = LoggerFactory.getLogger(BroadcastDiscovery.class);
    private static Boolean running = false;
    private static MulticastSocket socket;
    public static void main(String[] args) throws Exception {
        start(new DiscoveryDevice());

        Timer timer = new Timer();
        timer.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                System.err.println(DiscoveryDevice.ips.stream().collect(Collectors.joining(",")));
            }
        }, 1000, 10000);
    }

    /**
     * 发送一次广播消息
     */
    public static void discovery(){
        if(socket != null) {
            try {
                socket.send(new DatagramPacket(DISCOVERY_PROBE_MESSAGE.getBytes(), DISCOVERY_PROBE_MESSAGE.length(), InetAddress.getByName(DISCOVERY_ADDRESS_IPV4), DISCOVERY_PORT));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 开始发现
     * @param discoveryDevice
     */
    public static void start(DiscoveryDevice discoveryDevice){
        if(running){
            return;
        }
        running = true;
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    BroadcastDiscovery.logger.info("开始onvif搜索");
                    socket = new MulticastSocket(DISCOVERY_PORT);
                    InetAddress group = InetAddress.getByName(DISCOVERY_ADDRESS_IPV4);
                    socket.joinGroup(group);

                    discovery();

                    byte[] buffer = new byte[1024];
                    DatagramPacket packet = new DatagramPacket(buffer, buffer.length);

                    // 接收数据
                    while (running) {
                        socket.receive(packet);
                        String message = new String(packet.getData(), 0, packet.getLength());
                        BroadcastDiscovery.logger.debug("onvif response from {}:\r\n {}", packet.getAddress().getHostAddress(), message);
                        discoveryDevice.onDevice(packet.getAddress().getHostAddress());
                    }
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }).start();
    }

    /**
     * 停止
     */
    public static void stop(){
        running = false;
    }
}
